#include <iostream>
#include <string>
#include <list>
using namespace std;

class Shape 
{
public:
	virtual ~Shape() {};
	virtual float calcArea() = 0;
	virtual float calcPerimeter() = 0;
};

class Rectangle : public Shape
{
public:
	Rectangle(float w, float h);
	virtual ~Rectangle();
	virtual float calcArea();
	virtual float calcPerimeter();
private:
	float width;
	float height;
};

Rectangle::Rectangle(float w, float h)
    : width(w)
    , height(h)
{
    cout << "Rectangle()" << endl;
}

Rectangle::~Rectangle()
{
    cout << "~Rectangle()" << endl;
}

float Rectangle::calcArea()
{
    cout << "Rectangle::calcArea() = ";
    return width * height;
}

float Rectangle::calcPerimeter()
{
    cout << "Rectangle::calcPerimeter() = ";
    return 2 * (width + height);
}

class Circle : public Shape
{
public:
	Circle(float r);
	virtual ~Circle();
	virtual float calcArea();
	virtual float calcPerimeter();
private:
	const float Pi = 3.1415926;
	float radius;
};

Circle::Circle(float r) : radius(r)
{
    cout << "Circle()" << endl;
}

Circle::~Circle()
{
    cout << "~Circle()" << endl;
}

float Circle::calcArea()
{
    cout << "Circle::calcArea() = ";
    return Pi * radius * radius;
}

float Circle::calcPerimeter()
{
    cout << "Circle::calcPerimeter() = ";
    return 2 * Pi * radius;
}

void calc(list<Shape*> s)
{
    for (list<Shape*>::iterator it = s.begin(); it != s.end(); ++it)
    {
        cout << (*it)->calcArea() << endl;
        cout << (*it)->calcPerimeter() << endl;
    }    
}

int main()
{
    list<Shape*> shapes;
    shapes.push_back(new Rectangle(3, 4));
    shapes.push_back(new Circle(5));

    calc(shapes);

    for (list<Shape*>::iterator it = shapes.begin(); it != shapes.end();)
    {
        auto temp = (*it);
        delete temp;
        temp = nullptr;
        it = shapes.erase(it);
    } 
    
    return 0;
}
